﻿using System.Diagnostics;
using System.Runtime.InteropServices;
using Win32Proxy.Api;
using Win32Proxy.Structs;

namespace Win32Proxy.Helper
{
    public class WindowHelper
    {
        /// <summary>
        /// 查找窗体句柄
        /// </summary>
        /// <param name="lpClassName"></param>
        /// <param name="lpWindowName"></param>
        /// <returns></returns>
        public static IntPtr FindWindow(string? lpClassName, string? lpWindowName)
        {
            return User32.FindWindow(lpClassName, lpWindowName);
        }

        public static bool GetWindowRect(IntPtr hwnd, out RECT lpRect)
        {
            return User32.GetWindowRect(hwnd, out lpRect);
        }

        public static bool GetClientRect(IntPtr hwnd, out RECT lpRect)
        {
            return User32.GetClientRect(hwnd, out lpRect);
        }

        public static bool ClientToScreen(IntPtr hwnd, out Point lpPoint)
        {
            return User32.ClientToScreen(hwnd, out lpPoint);
        }

        public static bool ScreenToClient(IntPtr hwnd, out Point lpPoint)
        {
            return User32.ScreenToClient(hwnd, out lpPoint);
        }

        public static bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO info)
        {
            return User32.GetWindowInfo(hwnd, ref info);
        }

        public static Process? GetWindowProcessByName(string processName)
        {
            var p = Process.GetProcessesByName(processName);
            return p.FirstOrDefault();
        }

        /// <summary>
        /// 获取所有进程
        /// </summary>
        /// <returns></returns>
        public static List<Process> GetAllProcess()
        {
            return [.. Process.GetProcesses()];
        }

        /// <summary>
        /// 根据进程名称获取进程Handle
        /// </summary>
        /// <param name="processName"></param>
        /// <returns></returns>
        public static IntPtr GetWindowHandleByName(string processName)
        {
            using var p = GetWindowProcessByName(processName);
            if (p != null)
            {
                return p.MainWindowHandle;
            }
            else
            {
                return IntPtr.Zero;
            }
        }

        /// <summary>
        /// 根据句柄获取窗体的边框大小和位置
        /// </summary>
        /// <param name="hwnd">窗体句柄</param>
        /// <param name="clientInfo">是否为ClientRect</param>
        /// <returns></returns>
        public static System.Drawing.Rectangle GetWindowBounds(IntPtr hwnd, bool clientInfo = true)
        {
            //获取窗口大小
            WINDOWINFO info = new();
            info.cbSize = (uint)Marshal.SizeOf(info);
            if (!User32.GetWindowInfo(hwnd, ref info))
            {
                return System.Drawing.Rectangle.Empty;
            }
            System.Drawing.Rectangle rect;
            
            nint hMonitor = MonitorHelper.MonitorFromWindow(hwnd);
            var monitorInfo = MonitorHelper.GetMonitorInfo(hMonitor);
            if (monitorInfo.dwFlags == 1) //screen.Primary
            {
                if (clientInfo)
                    rect = new System.Drawing.Rectangle(info.rcClient.left, info.rcClient.top, info.rcClient.right - info.rcClient.left, info.rcClient.bottom - info.rcClient.top);
                else
                    rect = new System.Drawing.Rectangle(info.rcWindow.left, info.rcWindow.top, info.rcWindow.right - info.rcWindow.left, info.rcWindow.bottom - info.rcWindow.top);
            }
            else
            {
                var scaleX = MonitorHelper.DpiX / 96;
                var scaleY = MonitorHelper.DpiY / 96;

                if (clientInfo)
                {
                    int left = (int)(info.rcClient.left / scaleX);
                    int top = (int)(info.rcClient.top / scaleY);
                    int right = (int)(info.rcClient.right / scaleX);
                    int bottom = (int)(info.rcClient.bottom / scaleY);
                    rect = new System.Drawing.Rectangle(left, top, right - left, bottom - top);
                }
                else
                {
                    int left = (int)(info.rcWindow.left / scaleX);
                    int top = (int)(info.rcWindow.top / scaleY);
                    int right = (int)(info.rcWindow.right / scaleX);
                    int bottom = (int)(info.rcWindow.bottom / scaleY);
                    rect = new System.Drawing.Rectangle(left, top, right - left, bottom - top);
                }
                    
            }
            return rect;
        }

        /// <summary>
        /// 设置窗体的位置和大小、是否顶置
        /// </summary>
        /// <param name="hwnd">窗体句柄</param>
        /// <param name="location">位置</param>
        /// <param name="size">大小</param>
        /// <param name="fixWidth">宽度修正值</param>
        /// <param name="fixHeight">高度修正值</param>
        /// <param name="offX">x偏移量</param>
        /// <param name="offY">y偏移量</param>
        /// <param name="isTop">是否顶置</param>
        public static void SetWindowBounds(IntPtr hwnd, System.Drawing.Point location, System.Drawing.Size size, int fixWidth = 16, int fixHeight = 8, int offX = -8, int offY = 0, bool isTop = true)
        {
            //修正边距
            size.Width += fixWidth;
            size.Height += fixHeight;

            if (isTop)
                User32.SetWindowPos(hwnd, new IntPtr(-1), location.X + offX, location.Y + offY, size.Width, size.Height, 0);
            else
                User32.SetWindowPos(hwnd, new IntPtr(-2), location.X + offX, location.Y + offY, size.Width, size.Height, 0);
        }

        /// <summary>
        /// 窗口最大化
        /// </summary>
        /// <param name="hwnd"></param>
        public static void Maximize(IntPtr hwnd)
        {
            User32.ShowWindow(hwnd, Const.SW_MAXIMIZE);
        }
        /// <summary>
        /// 窗口最小化
        /// </summary>
        /// <param name="hwnd"></param>
        public static void Minimize(IntPtr hwnd)
        {
            User32.ShowWindow(hwnd, Const.SW_MINIMIZE);
        }
        /// <summary>
        /// 还原窗口
        /// </summary>
        /// <param name="hwnd"></param>
        public static void Normal(IntPtr hwnd)
        {
            User32.ShowWindow(hwnd, Const.SW_NORMAL);
        }
        /// <summary>
        /// 恢复窗口
        /// </summary>
        /// <param name="hwnd"></param>
        public static void Restore(IntPtr hwnd)
        {
            User32.ShowWindow(hwnd, Const.SW_RESTORE);
        }
        /// <summary>
        /// 显示窗口
        /// </summary>
        /// <param name="hwnd"></param>
        public static void Show(IntPtr hwnd)
        {
            User32.ShowWindow(hwnd, Const.SW_SHOW);
        }
        /// <summary>
        /// 隐藏窗口
        /// </summary>
        /// <param name="hwnd"></param>
        public static void Hide(IntPtr hwnd)
        {
            User32.ShowWindow(hwnd, Const.SW_HIDE);
        }
        /// <summary>
        /// 关闭窗口
        /// </summary>
        /// <param name="hwnd"></param>
        public static void Close(IntPtr hwnd)
        {
            User32.PostMessage((int)hwnd, Const.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }
    }
}
